package cn.iocoder.yudao.module.dating.service.smallNote;

import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.dating.controller.admin.smallNote.vo.SmallNoteLogPageReqVO;
import cn.iocoder.yudao.module.dating.controller.admin.smallNote.vo.SmallNotePageReqVO;
import cn.iocoder.yudao.module.dating.controller.admin.smallNote.vo.SmallNoteSaveReqVO;
import cn.iocoder.yudao.module.dating.controller.app.samllNote.vo.*;
import cn.iocoder.yudao.module.dating.dal.dataobject.smallNote.SmallNoteDO;
import cn.iocoder.yudao.module.dating.dal.dataobject.smallNote.SmallNoteLogDO;
import cn.iocoder.yudao.module.dating.dal.mysql.smallNote.SmallNoteLogMapper;
import cn.iocoder.yudao.module.dating.dal.mysql.smallNote.SmallNoteMapper;
import cn.iocoder.yudao.module.dating.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
import com.alibaba.excel.util.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.dating.enums.ErrorCodeConstants.SMALL_NOTE_NOT_EXISTS;
import static cn.iocoder.yudao.module.dating.enums.ErrorCodeConstants.SMALL_NOTE_NOT_MONEY;

/**
 * 小纸条 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class SmallNoteServiceImpl implements SmallNoteService {

    @Resource
    private SmallNoteMapper smallNoteMapper;
    @Resource
    private PayWalletService payWalletService;
    @Resource
    private SmallNoteLogMapper smallNoteLogMapper;

    @Override
    public Long createSmallNote(SmallNoteSaveReqVO createReqVO) {
        // 插入
        SmallNoteDO smallNote = BeanUtils.toBean(createReqVO, SmallNoteDO.class);
        smallNoteMapper.insert(smallNote);
        // 返回
        return smallNote.getId();
    }

    @Override
    public void updateSmallNote(SmallNoteSaveReqVO updateReqVO) {
        // 校验存在
        validateSmallNoteExists(updateReqVO.getId());
        // 更新
        SmallNoteDO updateObj = BeanUtils.toBean(updateReqVO, SmallNoteDO.class);
        smallNoteMapper.updateById(updateObj);
    }

    @Override
    public void deleteSmallNote(Long id) {
        // 校验存在
        validateSmallNoteExists(id);
        // 删除
        smallNoteMapper.deleteById(id);
    }

    private void validateSmallNoteExists(Long id) {
        if (smallNoteMapper.selectById(id) == null) {
            throw exception(SMALL_NOTE_NOT_EXISTS);
        }
    }

    @Override
    public SmallNoteDO getSmallNote(Long id) {
        return smallNoteMapper.selectById(id);
    }

    @Override
    public PageResult<SmallNoteDO> getSmallNotePage(SmallNotePageReqVO pageReqVO) {
        return smallNoteMapper.selectPage(pageReqVO);
    }

    @Override
    public AppSmallNoteTakeResVO infoSmallNoteById(Long id) {
        SmallNoteLogPageReqVO logVO = new SmallNoteLogPageReqVO();
        logVO.setTakeUserId(getLoginUserId());
        logVO.setStatusFlag(true);
        logVO.setNoteId(id);
        PageResult<SmallNoteLogDO> logVOResult = smallNoteLogMapper.selectPage(logVO);
        if (CollectionUtils.isEmpty(logVOResult.getList())) {
            // 继续循环
            throw new ServiceException(ErrorCodeConstants.SMALL_NOTE_NOT_EXISTS);
        }
        SmallNoteLogDO smallNoteLogDO = logVOResult.getList().get(0);
        return BeanUtils.toBean(smallNoteLogDO, AppSmallNoteTakeResVO.class);
    }

    @Override
    public AppSmallNoteTakeResVO takeSmallNoteById(Long id) {
        Integer fee = 3;
        PayWalletDO wallet = payWalletService.getOrCreateWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue());
        int balance = wallet.getBalance() - fee;
        if (balance < 0) {
            throw new ServiceException(SMALL_NOTE_NOT_MONEY);
        }
        SmallNoteDO smallNoteDO = smallNoteMapper.selectById(id);
        AppSmallNoteTakeReqVO createReqVO = new AppSmallNoteTakeReqVO();
        createReqVO.setId(id);
        // 得到结果，插入抽取日志表
        SmallNoteLogDO smallNoteLogDO = new SmallNoteLogDO();
        smallNoteLogDO.setConditions(JsonUtils.toJsonString(createReqVO));
        smallNoteLogDO.setTakeUserId(getLoginUserId());
        if (smallNoteDO != null) {
            smallNoteLogDO.setUserId(smallNoteDO.getUserId());
            smallNoteLogDO.setAccount(smallNoteDO.getAccount());
            smallNoteLogDO.setAccountImg(smallNoteDO.getAccountImg());
            smallNoteLogDO.setSex(smallNoteDO.getSex());
            smallNoteLogDO.setCity(smallNoteDO.getCity());
            smallNoteLogDO.setArea(smallNoteDO.getArea());
            smallNoteLogDO.setProvince(smallNoteDO.getProvince());
            smallNoteLogDO.setBoxType(smallNoteDO.getBoxType());
            smallNoteLogDO.setDesp(smallNoteDO.getDesp());
            smallNoteLogDO.setImages(smallNoteDO.getImages());
            smallNoteLogDO.setHighFlag(smallNoteDO.getHighFlag());
            smallNoteLogDO.setNoteId(smallNoteDO.getId());
            smallNoteLogDO.setFee(fee);
            smallNoteLogDO.setStatusFlag(true);
            smallNoteDO.setExtractNum(smallNoteDO.getExtractNum() + 1);
            smallNoteDO.setViews(smallNoteDO.getViews() + 1);
            // 扣费
            payWalletService.reduceWalletBalance(wallet.getId(), smallNoteDO.getId(), PayWalletBizTypeEnum.PAYMENT, fee);
            if (smallNoteDO.getExtractDestroyNum() > 0 && smallNoteDO.getExtractNum() >= smallNoteDO.getExtractDestroyNum()) {
                smallNoteDO.setDestroyFlag(true);
            }
            smallNoteMapper.updateById(smallNoteDO);
        }
        if (smallNoteDO == null) {
            smallNoteLogDO.setStatusFlag(false);
        }
        smallNoteLogMapper.insert(smallNoteLogDO);
        // 返回结果
        AppSmallNoteTakeResVO takeResVO = BeanUtils.toBean(smallNoteDO, AppSmallNoteTakeResVO.class);
        return takeResVO;
    }

    @Override
    public AppSmallNoteTakeResVO takeSmallNote(AppSmallNoteTakeReqVO createReqVO) {
        Integer fee = 1;
        PayWalletDO wallet = payWalletService.getOrCreateWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue());
        int balance = wallet.getBalance() - fee;
        if (balance < 0) {
            throw new ServiceException(SMALL_NOTE_NOT_MONEY);
        }
        // 查询符合条件的盲盒
        SmallNoteDO smallNoteDO = getSmallNoteDO(createReqVO);
        // 得到结果，插入抽取日志表
        SmallNoteLogDO smallNoteLogDO = new SmallNoteLogDO();
        smallNoteLogDO.setConditions(JsonUtils.toJsonString(createReqVO));
        smallNoteLogDO.setTakeUserId(getLoginUserId());
        if (smallNoteDO != null) {
            smallNoteLogDO.setUserId(smallNoteDO.getUserId());
            smallNoteLogDO.setAccount(smallNoteDO.getAccount());
            smallNoteLogDO.setAccountImg(smallNoteDO.getAccountImg());
            smallNoteLogDO.setSex(smallNoteDO.getSex());
            smallNoteLogDO.setCity(smallNoteDO.getCity());
            smallNoteLogDO.setArea(smallNoteDO.getArea());
            smallNoteLogDO.setProvince(smallNoteDO.getProvince());
            smallNoteLogDO.setBoxType(smallNoteDO.getBoxType());
            smallNoteLogDO.setDesp(smallNoteDO.getDesp());
            smallNoteLogDO.setImages(smallNoteDO.getImages());
            smallNoteLogDO.setHighFlag(smallNoteDO.getHighFlag());
            smallNoteLogDO.setNoteId(smallNoteDO.getId());
            smallNoteLogDO.setFee(fee);
            smallNoteLogDO.setStatusFlag(true);
            smallNoteDO.setExtractNum(smallNoteDO.getExtractNum() + 1);
            smallNoteDO.setViews(smallNoteDO.getViews() + 1);
            // 扣费
            payWalletService.reduceWalletBalance(wallet.getId(), smallNoteDO.getId(), PayWalletBizTypeEnum.PAYMENT, fee);
            if (smallNoteDO.getExtractDestroyNum() > 0 && smallNoteDO.getExtractNum() >= smallNoteDO.getExtractDestroyNum()) {
                smallNoteDO.setDestroyFlag(true);
            }
            smallNoteMapper.updateById(smallNoteDO);
        }
        if (smallNoteDO == null) {
            smallNoteLogDO.setStatusFlag(false);
        }
        smallNoteLogMapper.insert(smallNoteLogDO);
        if (smallNoteDO == null) {
            throw new ServiceException(ErrorCodeConstants.SMALL_NOTE_NOT_FOUNT);
        }
        // 返回结果
        AppSmallNoteTakeResVO takeResVO = BeanUtils.toBean(smallNoteDO, AppSmallNoteTakeResVO.class);
        return takeResVO;
    }

    private SmallNoteDO getSmallNoteDO(AppSmallNoteTakeReqVO createReqVO) {
        int retryCount = 0;
        SmallNoteDO result = null;
        do {
            SmallNoteDO smallNoteDO = smallNoteMapper.selectNote(createReqVO);
            if (smallNoteDO == null) {
                return null;
            }
            // 排除掉已经抽取到的
            Long loginUserId = getLoginUserId();
            if (loginUserId != null) {
                SmallNoteLogPageReqVO logVO = new SmallNoteLogPageReqVO();
                logVO.setTakeUserId(loginUserId);
                logVO.setStatusFlag(true);
                logVO.setNoteId(smallNoteDO.getId());
                PageResult<SmallNoteLogDO> logVOResult = smallNoteLogMapper.selectPage(logVO);
                if (CollectionUtils.isNotEmpty(logVOResult.getList())) {
                    // 继续循环
                    retryCount++;
                } else {
                    result = smallNoteDO;
                    // 跳出循环
                    break;
                }
            } else {
                result = smallNoteDO;
                // 跳出循环
                break;
            }
        } while (retryCount < 3);

        return result;
    }

    @Override
    public Long createAppSmallNote(AppSmallNoteReqVO createReqVO) {
        Integer fee = 1;
        // 增加一些投递限制
        if (Boolean.TRUE.equals(createReqVO.getPubFlag())) {
            fee = 3;
        }
        if (Objects.equals(createReqVO.getBoxType(), "F")) {
            fee = 0;
        }
        PayWalletDO wallet = payWalletService.getOrCreateWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue());
        if (fee > 0) {
            int balance = wallet.getBalance() - fee;
            if (balance < 0) {
                throw new ServiceException(SMALL_NOTE_NOT_MONEY);
            }
        }
        // 插入
        SmallNoteDO smallNote = BeanUtils.toBean(createReqVO, SmallNoteDO.class);
        Integer lifeCycle = createReqVO.getLifeCycle();
        if (lifeCycle == 1) {
            smallNote.setExtractDestroyNum(-1);
        } else {
            smallNote.setExtractDestroyNum(1);
        }
        smallNote.setUserId(getLoginUserId());
        smallNoteMapper.insert(smallNote);
        if (fee > 0) {
            payWalletService.reduceWalletBalance(wallet.getId(), smallNote.getId(), PayWalletBizTypeEnum.PAYMENT, fee);
        }
        // 返回
        return smallNote.getId();
    }

    @Override
    public PageResult<AppSmallNoteTakeResVO> pushList(AppSmallNotePageReqVO pageReqVO) {
        SmallNotePageReqVO reqVO = BeanUtils.toBean(pageReqVO, SmallNotePageReqVO.class);
        reqVO.setUserId(getLoginUserId());
        PageResult<SmallNoteDO> pageResult = smallNoteMapper.selectPage(reqVO);
        return BeanUtils.toBean(pageResult, AppSmallNoteTakeResVO.class);
    }

    @Override
    public PageResult<AppSmallNoteTakeResVO> takeList(AppSmallNotePageReqVO pageReqVO) {
        SmallNoteLogPageReqVO reqVO = BeanUtils.toBean(pageReqVO, SmallNoteLogPageReqVO.class);
        reqVO.setTakeUserId(getLoginUserId());
        PageResult<SmallNoteLogDO> pageResult = smallNoteLogMapper.selectPage(reqVO);
        return BeanUtils.toBean(pageResult, AppSmallNoteTakeResVO.class);
    }

    @Override
    public PageResult<AppSmallNoteCardResVO> topList(AppSmallNotePageReqVO pageReqVO) {
        SmallNotePageReqVO reqVO = BeanUtils.toBean(pageReqVO, SmallNotePageReqVO.class);
        reqVO.setPubFlag(true);
        reqVO.setHighFlag(true);
        reqVO.setStatusFlag(true);
        reqVO.setDestroyFlag(false);
        PageResult<SmallNoteDO> pageResult = smallNoteMapper.selectPage(reqVO);
        List<AppSmallNoteCardResVO> voList = pageResult.getList().stream().map(smallNoteDO -> {
            AppSmallNoteCardResVO appSmallNoteCardResVO = BeanUtils.toBean(smallNoteDO, AppSmallNoteCardResVO.class);
            if (StringUtils.isNotBlank(smallNoteDO.getImages())) {
                String[] images = smallNoteDO.getImages().split(",");
                List<String> imagesList = Arrays.stream(images).collect(Collectors.toList());
                appSmallNoteCardResVO.setImageList(imagesList);
            }
            // 查询是否购买
            Long loginUserId = getLoginUserId();
            if (loginUserId != null) {
                SmallNoteLogPageReqVO logVO = new SmallNoteLogPageReqVO();
                logVO.setTakeUserId(loginUserId);
                logVO.setStatusFlag(true);
                logVO.setNoteId(smallNoteDO.getId());
                PageResult<SmallNoteLogDO> logVOResult = smallNoteLogMapper.selectPage(logVO);
                if (CollectionUtils.isNotEmpty(logVOResult.getList())) {
                    appSmallNoteCardResVO.setViewType(1);
                }
            }
            return appSmallNoteCardResVO;
        }).collect(Collectors.toList());
        return new PageResult<>(voList, pageResult.getTotal());
    }

    @Override
    public PageResult<AppSmallNoteCardResVO> squareList(AppSmallNotePageReqVO pageReqVO) {
        SmallNotePageReqVO reqVO = BeanUtils.toBean(pageReqVO, SmallNotePageReqVO.class);
        reqVO.setPubFlag(true);
        reqVO.setStatusFlag(true);
        reqVO.setDestroyFlag(false);
        PageResult<SmallNoteDO> pageResult = smallNoteMapper.selectPage(reqVO);
        List<AppSmallNoteCardResVO> voList = pageResult.getList().stream().map(smallNoteDO -> {
            AppSmallNoteCardResVO appSmallNoteCardResVO = BeanUtils.toBean(smallNoteDO, AppSmallNoteCardResVO.class);
            if (StringUtils.isNotBlank(smallNoteDO.getImages())) {
                String[] images = smallNoteDO.getImages().split(",");
                List<String> imagesList = Arrays.stream(images).collect(Collectors.toList());
                appSmallNoteCardResVO.setImageList(imagesList);
            }
            // 查询是否购买
            Long loginUserId = getLoginUserId();
            if (loginUserId != null) {
                SmallNoteLogPageReqVO logVO = new SmallNoteLogPageReqVO();
                logVO.setTakeUserId(loginUserId);
                logVO.setStatusFlag(true);
                logVO.setNoteId(smallNoteDO.getId());
                PageResult<SmallNoteLogDO> logVOResult = smallNoteLogMapper.selectPage(logVO);
                if (CollectionUtils.isNotEmpty(logVOResult.getList())) {
                    appSmallNoteCardResVO.setViewType(1);
                }
            }
            return appSmallNoteCardResVO;
        }).collect(Collectors.toList());
        return new PageResult<>(voList, pageResult.getTotal());
    }
}